import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  Query,
  Res,
  BadRequestException,
  HttpStatus,
  Logger,
  Req,
  UseGuards,
} from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import {
  ApiBody,
  ApiOperation,
  ApiParam,
  ApiQuery,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import { ListUserDto } from './dto/list-user.dto';
import { ExcelService } from 'src/common/excel/excel.service';
import { ResetPasswordDto } from './dto/reset-password.dto';
import { MetricsService } from 'src/common/metrics/metrics.service';
import { Roles } from './roles.decorator';
import { RolesGuard } from './roles.guard';
import { UpdatePasswordDto } from './dto/update-password.dto';

@Controller('user')
@UseGuards(RolesGuard)
@ApiTags('用户及角色管理')
export class UserController {
  private logger = new Logger('UserController');
  constructor(
    private readonly userService: UserService,
    private readonly excelService: ExcelService,
    private readonly metricsService: MetricsService,
  ) {}

  @Get('roleList')
  @ApiOperation({
    summary: '查询角色列表',
    description: '获取所有角色列表，用来做角色权限管理',
  })
  roleList() {
    return this.userService.roleList();
  }

  @Post()
  @Roles('systemAdmin', 'admin')
  @ApiOperation({
    summary: '创建用户',
    description: '创建用户',
  })
  @ApiBody({ type: CreateUserDto })
  @ApiResponse({ status: 200, description: '创建成功' })
  create(@Body() createUserDto: CreateUserDto, @Req() req) {
    // 服务监控代码-与业务无关
    this.metricsService.incrementRequestCount('Post', '/user');
    return this.userService.create(createUserDto, req);
  }

  @Get()
  @ApiOperation({
    summary: '查询用户列表',
    description: '查询用户列表',
  })
  @ApiQuery({ name: 'query', type: ListUserDto })
  @ApiResponse({ status: 200, description: '查询用户成功' })
  findAll(@Query() query: ListUserDto) {
    return this.userService.findAllByPage(query);
  }

  @Get(':id')
  @ApiOperation({
    summary: '查询用户',
    description: '根据id查询用户',
  })
  @ApiParam({ name: 'id', description: '账号id' })
  @ApiResponse({ status: 200, description: '查询用户成功' })
  findOne(@Param('id') id: string) {
    return this.userService.findOne(+id);
  }

  @Patch(':id')
  @Roles('systemAdmin', 'admin')
  @ApiOperation({
    summary: '更新用户',
    description: '根据id更新用户',
  })
  @ApiParam({ name: 'id', description: '账号id' })
  @ApiBody({ description: '账号信息', type: UpdateUserDto })
  @ApiResponse({ status: 200, description: '更新成功' })
  update(
    @Param('id') id: string,
    @Body() updateUserDto: UpdateUserDto,
    @Req() req,
  ) {
    return this.userService.update(+id, updateUserDto, req);
  }

  @Delete(':id')
  @Roles('systemAdmin', 'admin')
  @ApiOperation({
    summary: '删除用户',
    description: '根据id删除用户',
  })
  @ApiParam({ name: 'id', description: '账号id' })
  @ApiResponse({ status: 200, description: '删除成功' })
  remove(@Param('id') id: string, @Req() req) {
    return this.userService.softDeleteUser(+id, req);
  }

  @Delete()
  @Roles('systemAdmin', 'admin')
  @ApiOperation({
    summary: '批量删除用户',
    description: '根据ids删除用户',
  })
  @ApiBody({ description: '账号id列表' })
  @ApiResponse({ status: 200, description: '批量删除用户成功' })
  removeUsers(@Body('ids') ids: number[], @Req() req) {
    this.logger.log('@@@ ids', ids);
    return this.userService.softDeleteUsers(ids, req);
  }

  @Post('/userSearchExport')
  @Roles('systemAdmin', 'admin', 'user')
  @ApiOperation({
    summary: '用户表查询导出',
    description: '用户表查询导出',
  })
  @ApiBody({ type: ListUserDto })
  @ApiResponse({ status: 200, description: '用户表查询导出成功' })
  async userSearchExport(@Body() body: ListUserDto, @Res() res): Promise<void> {
    const userList = await this.userService.findAll(body);

    if (!userList?.length) {
      throw new BadRequestException('导出数据为空');
    }

    try {
      // 导出为 Excel 文件
      const filename = encodeURIComponent('用户表.xlsx');
      const buffer = this.excelService.exportAsExcelFile(userList);

      this.logger.log('@@@ buffer', buffer);
      this.logger.log('@@@ filename', filename);

      // 设置响应头
      res.setHeader(
        'Content-Type',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      );
      res.setHeader('Content-Disposition', `attachment; filename=${filename}`);

      // 发送文件
      res.status(HttpStatus.OK).end(buffer);
    } catch (error) {
      this.logger.error('@@@ 用户表查询导出接口调用失败：', error);
      throw new BadRequestException('用户表查询导出接口调用失败');
    }
  }

  @Post('/userSelectExport')
  @Roles('systemAdmin', 'admin', 'user')
  @ApiOperation({
    summary: '用户表勾选导出',
    description: '用户表勾选导出',
  })
  @ApiBody({ description: '账号id列表' })
  @ApiResponse({ status: 200, description: '用户表勾选导出成功' })
  async userSelectExport(
    @Body('ids') ids: number[],
    @Res() res,
  ): Promise<void> {
    const userList = await this.userService.findByIds(ids);

    if (!userList?.length) {
      throw new BadRequestException('导出数据为空');
    }

    try {
      // 导出为 Excel 文件
      const filename = encodeURIComponent('用户勾选表.xlsx');
      const buffer = this.excelService.exportAsExcelFile(userList);

      this.logger.log('@@@ buffer', buffer);
      this.logger.log('@@@ filename', filename);

      // 设置响应头
      res.setHeader(
        'Content-Type',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      );
      res.setHeader('Content-Disposition', `attachment; filename=${filename}`);

      // 发送文件
      res.status(HttpStatus.OK).end(buffer);
    } catch (error) {
      this.logger.error('@@@ 用户表勾选导出接口调用失败：', error);
      throw new BadRequestException('用户表勾选导出接口调用失败');
    }
  }

  @Post('/resetPassword')
  @Roles('systemAdmin', 'admin')
  @ApiOperation({
    summary: '用户重置密码',
    description: '用户重置密码',
  })
  @ApiBody({ type: ResetPasswordDto })
  @ApiResponse({ status: 200, description: '用户重置密码成功' })
  async resetPassword(@Body() body: ResetPasswordDto, @Req() req) {
    return this.userService.resetPassword(body, req);
  }

  @Post('/userUpdatePassword')
  @ApiOperation({
    summary: '用户修改密码',
    description: '用户修改密码',
  })
  @ApiBody({ type: UpdatePasswordDto })
  @ApiResponse({ status: 200, description: '用户修改密码成功' })
  async userUpdatePassword(@Body() body: UpdatePasswordDto, @Req() req) {
    return this.userService.userUpdatePassword(body, req);
  }
}
